/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.web.gwt.form.server.service.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.genia.toolbox.basics.i18n.EnumDescriptable;
import com.genia.toolbox.basics.i18n.I18nMessage;
import com.genia.toolbox.basics.i18n.impl.I18nMessageImpl;
import com.genia.toolbox.web.gwt.basics.client.i18n.GwtI18nMessage;
import com.genia.toolbox.web.gwt.basics.client.oracle.SimpleSuggestion;
import com.genia.toolbox.web.gwt.form.client.form.ButtonItem;
import com.genia.toolbox.web.gwt.form.client.form.Form;
import com.genia.toolbox.web.gwt.form.client.form.ValuedItemEntryList;
import com.genia.toolbox.web.gwt.form.client.form.impl.ButtonItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.CheckBoxItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.DateItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.DateTimeItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.DynamicListBoxItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.DynamicRadioButtonItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.FileUploadItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.HorizontalFormImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.I18nTextAreaItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.I18nTextBoxItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.ImageItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.InlineFormMultipleItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.InlineFormSimpleItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.LabeledFormImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.ListBoxItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.MultipleFileUploadItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.PasswordBoxItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.RadioButtonItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.RichTextAreaItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.SimpleValuedItemEntryListImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.TabFormImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.TextAreaItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.TextBoxItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.TimeItemImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.ValuedItemEntryImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.VerticalFormImpl;
import com.genia.toolbox.web.gwt.form.client.validator.impl.IterativeRegularExpressionValidator;
import com.genia.toolbox.web.gwt.form.client.validator.impl.LongValidator;
import com.genia.toolbox.web.gwt.form.client.value.DataIdentifier;
import com.genia.toolbox.web.gwt.form.client.value.FormSimpleValue;
import com.genia.toolbox.web.gwt.form.client.value.FormValues;
import com.genia.toolbox.web.gwt.form.client.value.impl.DataIdentifierImpl;
import com.genia.toolbox.web.gwt.form.client.value.impl.FormSimpleValueImpl;
import com.genia.toolbox.web.gwt.form.client.value.impl.FormValuesImpl;
import com.genia.toolbox.web.gwt.form.server.provider.FormProvider;
import com.genia.toolbox.web.gwt.form.server.spring.factory.EnumDescriptableValuedItemEntryListFactory;

public class DemoFormGenerator
    implements FormProvider
{

  private static String i18nTextAreaName = null;

  private static TabFormImpl demo = null;

  private static List<FormValues> demoValues = new ArrayList<FormValues>();

  private static String[] values = { "foo", "bar", "baz", "quz", "hello", "world", "dupont", "durand", "bellocq", "lerman", "boungnarith", "daoud", "leonardi", "sigalo", "guenebaud" };

  /**
   * String label from properties files.
   */
  private static String tBoxLabel = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.lastName";

  private static String pBoxLabel = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.password";

  private static String listBoxLabel = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.listBox";

  private static String radioButtonLabel = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.radioButton";

  private static String checkBoxLabel = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.checkBox";

  private static String labelMessage = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.labelItem";

  private static String richTAreaMessage = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.RichTextAreaItem";

  private static String tab1Message = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.tab1";

  private static String tab2Message = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.tab2";

  private static String tab3Message = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.tab3";

  private static String tArea = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.textarea";

  private static String fileUploadKey = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.fileUpload";

  private static String dateKey = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.date";

  private static String inlineSimpleFormKey = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.inlineSimpleForm";

  private static String inlineMultipleFormKey = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.inlineMultipleForm";

  private static String buttonNoneFormKey = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.ButtonNone";

  private static String buttonBackFormKey = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.ButtonBack";

  private static String buttonResetFormKey = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.ButtonReset";

  private static String buttonGoogleFormKey = "com.genia.toolbox.web.gwt.form.server.service.impl.FakeFormService.ButtonGoogle";

  /**
   * i18nMessages label.
   */
  private static GwtI18nMessage i18nMessageLabel = new GwtI18nMessage(labelMessage);

  private static GwtI18nMessage i18nMessageTBox = new GwtI18nMessage(tBoxLabel);

  private static GwtI18nMessage i18nMessageRadioButton = new GwtI18nMessage(radioButtonLabel);

  private static GwtI18nMessage i18nMessagePasswBox = new GwtI18nMessage(pBoxLabel);

  private static GwtI18nMessage i18nMessageListBox = new GwtI18nMessage(listBoxLabel);

  private static GwtI18nMessage i18nMessageCheckBox = new GwtI18nMessage(checkBoxLabel);

  private static GwtI18nMessage i18nMessageRichTextArea = new GwtI18nMessage(richTAreaMessage);

  private static GwtI18nMessage i18nMessageTab1 = new GwtI18nMessage(tab1Message);

  private static GwtI18nMessage i18nMessageTab2 = new GwtI18nMessage(tab2Message);

  private static GwtI18nMessage i18nMessageTab3 = new GwtI18nMessage(tab3Message);

  private static GwtI18nMessage i18nMessageTextArea = new GwtI18nMessage(tArea);

  private static GwtI18nMessage i18nMessageTextBox = new GwtI18nMessage(tBoxLabel);

  private static GwtI18nMessage i18nMessageDynamicListBox = new GwtI18nMessage(listBoxLabel);

  private static GwtI18nMessage i18nMessageDynamicRadioButton = new GwtI18nMessage(radioButtonLabel);

  private static GwtI18nMessage i18nMessageFileUpload = new GwtI18nMessage(fileUploadKey);

  private static GwtI18nMessage i18nDate = new GwtI18nMessage(dateKey);

  private static GwtI18nMessage i18nInlineSimpleForm = new GwtI18nMessage(inlineSimpleFormKey);

  private static GwtI18nMessage i18nInlineMultipleForm = new GwtI18nMessage(inlineMultipleFormKey);

  private static GwtI18nMessage buttonNoneForm = new GwtI18nMessage(buttonNoneFormKey);

  private static GwtI18nMessage buttonBackForm = new GwtI18nMessage(buttonBackFormKey);

  private static GwtI18nMessage buttonResetForm = new GwtI18nMessage(buttonResetFormKey);

  private static GwtI18nMessage buttonGoogleForm = new GwtI18nMessage(buttonGoogleFormKey);

  private static int index = 0;

  private static Set<String> itemNames = new HashSet<String>();



  private static String getName()
  {
    final String name = "name" + (index++);
    itemNames.add(name);
    return name;
  }



  private FormValues getInitFormValues()
  {
    final FormValuesImpl newFormValues = new FormValuesImpl();
    getForm(null);
    newFormValues.setDataIdentifier(new DataIdentifierImpl());
    newFormValues.setFormIdentifier("demo");
    for (final String name : itemNames) {
      final String index = name.substring(4);
      final FormSimpleValueImpl formSimpleValue = new FormSimpleValueImpl();
      formSimpleValue.setName(name);
      formSimpleValue.setValue(index);
      newFormValues.addFormSimpleValue(formSimpleValue);
    }

    List<String> description = new ArrayList<String>();
    description.add("en::text in english");
    description.add("fr::text in french");
    FormSimpleValue formSimpleValue = newFormValues.getFormSimpleValue(i18nTextAreaName);
    formSimpleValue.setValues(description);

    return newFormValues;
  }



  public FormValues getInitialValue(final DataIdentifier dataIdentifier)
  {

    if (dataIdentifier.getIdentifier() == null) {
      return getInitFormValues();
    }
    final Integer id = Integer.valueOf(dataIdentifier.getIdentifier());
    return demoValues.get(id);
  }



  public synchronized FormValues saveForm(final FormValues newValues)
  {

    if (newValues.getDataIdentifier().getIdentifier() == null) {
      newValues.getDataIdentifier().setIdentifier(String.valueOf(demoValues.size()));
      demoValues.add(newValues);
    }
    else {
      demoValues.set(Integer.valueOf(newValues.getDataIdentifier().getIdentifier()), newValues);
    }

    return newValues;
  }

  private enum Label
      implements EnumDescriptable
  {
    V1(labelMessage),
    V2(tBoxLabel),
    V3(pBoxLabel),
    V4(fileUploadKey);

    private I18nMessage description;



    private Label(String key)
    {
      this.description = new I18nMessageImpl(key);
    }



    public I18nMessage getDescription()
    {
      return description;
    }



    public int getOrdinal()
    {
      return ordinal();
    }

  }



  @SuppressWarnings("unchecked")
  private static ValuedItemEntryList getSubLabels()
  {
    final ValuedItemEntryList res = new SimpleValuedItemEntryListImpl();
    ValuedItemEntryImpl viei = null;
    viei = new ValuedItemEntryImpl();
    viei.setLabel(i18nMessageLabel);
    viei.setValue("1");
    res.getValuedItemEntries().add(viei);
    viei = new ValuedItemEntryImpl();
    viei.setLabel(i18nMessageTBox);
    viei.setValue("2");
    res.getValuedItemEntries().add(viei);
    viei = new ValuedItemEntryImpl();
    viei.setLabel(i18nMessagePasswBox);
    viei.setValue("3");
    res.getValuedItemEntries().add(viei);
    return res;
  }



  private static ValuedItemEntryList getEnumSubLabels()
  {
    final EnumDescriptableValuedItemEntryListFactory factory = new EnumDescriptableValuedItemEntryListFactory();
    factory.setEnumClassName(Label.class.getName());
    return (ValuedItemEntryList) factory.getObject();
  }



  public Form getForm(DataIdentifier dataIdentifier)
  {
    if (demo == null) {
      demo = new TabFormImpl();
      demo.setName("tabFormDemo");

      final LabeledFormImpl firstForm = new LabeledFormImpl();
      firstForm.setName("firstForm");
      firstForm.setLabel(i18nMessageTab1);

      final VerticalFormImpl vForm = new VerticalFormImpl();
      vForm.setName("vFormName1");
      firstForm.setSubForm(vForm);

      demo.addForm(firstForm);

      /**
       * ************************************************First
       * Panel*******************************************
       */
      // Nom textBox
      final TextBoxItemImpl nomTextBox = new TextBoxItemImpl();
      nomTextBox.setLabelKey(i18nMessageTBox);
      nomTextBox.setName(getName());

      IterativeRegularExpressionValidator irev = new IterativeRegularExpressionValidator();
      irev.setRegularExpression("aaaaaa");

      nomTextBox.setValidator(irev);

      // Password
      final PasswordBoxItemImpl passBox = new PasswordBoxItemImpl();
      passBox.setLabelKey(i18nMessagePasswBox);
      passBox.setName(getName());
      passBox.setValidator(new LongValidator());

      final ListBoxItemImpl ageListBox = new ListBoxItemImpl();
      ageListBox.setLabelKey(i18nMessageListBox);
      ageListBox.setName(getName());
      ageListBox.setVisibleItemCount(1);
      ageListBox.setEntries(getSubLabels());

      // set the validator.
      ageListBox.setValidator(new LongValidator(0, 2));

      final VerticalFormImpl vPanel1 = new VerticalFormImpl();
      vPanel1.setName("vPanel1");
      vPanel1.addForm(nomTextBox);
      vPanel1.addForm(passBox);
      vPanel1.addForm(ageListBox);

      /*
       * Second Panel
       */
      // String[] subRadio={"Male", "Femelle"};
      // RadioButton.
      final RadioButtonItemImpl radioButton = new RadioButtonItemImpl();
      radioButton.setLabelKey(i18nMessageRadioButton);
      radioButton.setName(getName());
      radioButton.setEntries(getEnumSubLabels());
      radioButton.setVerticalDisplay(true);

      // set the validator.
      radioButton.setValidator(new LongValidator(0, 2));

      // checkBox
      final CheckBoxItemImpl checkBox1 = new CheckBoxItemImpl();
      checkBox1.setLabelKey(i18nMessageCheckBox);
      checkBox1.setName(getName());

      final CheckBoxItemImpl checkBox2 = new CheckBoxItemImpl();
      checkBox2.setLabelKey(i18nMessageCheckBox);
      checkBox2.setName(getName());
      // checkBox2.setValidator(new LongValidator());

      // PanelCheckbox
      final VerticalFormImpl checkPanel = new VerticalFormImpl();
      checkPanel.setName("checkPanel");
      checkPanel.addForm(checkBox1);
      checkPanel.addForm(checkBox2);

      final HorizontalFormImpl hPanel2 = new HorizontalFormImpl();
      hPanel2.setName("hPanel2");
      hPanel2.addForm(radioButton);
      hPanel2.addForm(checkPanel);

      /**
       * ************************************************Panel
       * three*******************************************
       */

      vForm.addForm(vPanel1);
      vForm.addForm(hPanel2);

      final FileUploadItemImpl fileUpload = new FileUploadItemImpl();
      fileUpload.setName(getName());
      fileUpload.setLabelKey(i18nMessageFileUpload);
      vForm.addForm(fileUpload);

      final MultipleFileUploadItemImpl multipleFileUpload = new MultipleFileUploadItemImpl();
      multipleFileUpload.setName(getName());
      multipleFileUpload.setLabelKey(i18nMessageFileUpload);
      vForm.addForm(multipleFileUpload);

      final DateItemImpl dateItem = new DateItemImpl();
      dateItem.setName(getName());
      dateItem.setLabelKey(i18nDate);
      dateItem.setNullable(true);
      dateItem.setDateFormat("yyyy/MM/dd yyyy");
      vForm.addForm(dateItem);

      final DateItemImpl dateItem2 = new DateItemImpl();
      dateItem2.setName(getName());
      dateItem2.setLabelKey(i18nDate);
      vForm.addForm(dateItem2);

      final TimeItemImpl timeItem = new TimeItemImpl();
      timeItem.setName(getName());
      timeItem.setLabelKey(i18nDate);
      timeItem.setNullable(true);
      vForm.addForm(timeItem);

      final DateTimeItemImpl dateTimeItem = new DateTimeItemImpl();
      dateTimeItem.setName(getName());
      dateTimeItem.setLabelKey(i18nDate);
      dateTimeItem.setNullable(true);
      vForm.addForm(dateTimeItem);

      final I18nTextAreaItemImpl i18nTextArea = new I18nTextAreaItemImpl();
      i18nTextArea.setName(getName());
      i18nTextArea.setLabelKey(i18nMessageTextArea);
      vForm.addForm(i18nTextArea);

      final I18nTextBoxItemImpl i18nBoxArea = new I18nTextBoxItemImpl();
      i18nTextAreaName = getName();
      i18nBoxArea.setName(i18nTextAreaName);
      i18nBoxArea.setLabelKey(i18nMessageTextBox);
      vForm.addForm(i18nBoxArea);

      final DynamicListBoxItemImpl dynamicListBoxItem = new DynamicListBoxItemImpl();
      dynamicListBoxItem.setName(getName());
      dynamicListBoxItem.setLabelKey(i18nMessageDynamicListBox);
      vForm.addForm(dynamicListBoxItem);

      final DynamicRadioButtonItemImpl dynamicRadioButtonItem = new DynamicRadioButtonItemImpl();
      dynamicRadioButtonItem.setName(getName());
      dynamicRadioButtonItem.setLabelKey(i18nMessageDynamicRadioButton);
      dynamicRadioButtonItem.setValidator(new LongValidator(0, 2));
      vForm.addForm(dynamicRadioButtonItem);

      HorizontalFormImpl hf = new HorizontalFormImpl();
      hf.setName("horizontalForm");

      final InlineFormSimpleItemImpl inlineFormSimpleItem = new InlineFormSimpleItemImpl();
      inlineFormSimpleItem.setLabelKey(i18nInlineSimpleForm);
      inlineFormSimpleItem.setName(getName());
      inlineFormSimpleItem.setInlineFormIdentifier("form1");

      final InlineFormMultipleItemImpl inlineFormMultipleItem = new InlineFormMultipleItemImpl();
      inlineFormMultipleItem.setLabelKey(i18nInlineMultipleForm);
      inlineFormMultipleItem.setName(getName());
      inlineFormMultipleItem.setSortable(true);
      inlineFormMultipleItem.setInlineFormIdentifier("form2");

      hf.addForm(inlineFormSimpleItem);
      hf.addForm(inlineFormMultipleItem);
      vForm.addForm(hf);

      final InlineFormSimpleItemImpl inlineFormSimpleItem2 = new InlineFormSimpleItemImpl();
      inlineFormSimpleItem2.setLabelKey(i18nInlineSimpleForm);
      inlineFormSimpleItem2.setName(getName());
      inlineFormSimpleItem2.setInlineFormIdentifier("form1");
      inlineFormSimpleItem2.setNullable(true);
      vForm.addForm(inlineFormSimpleItem2);

      ButtonItemImpl button = new ButtonItemImpl();

      button.setLabelKey(buttonNoneForm);
      button.setName(getName());
      button.setAction(ButtonItem.NONE_ACTION);
      button.setSave(true);
      vForm.addForm(button);

      button = new ButtonItemImpl();
      button.setLabelKey(buttonBackForm);
      button.setName(getName());
      button.setAction(ButtonItem.BACK_ACTION);
      button.setSave(false);
      vForm.addForm(button);

      button = new ButtonItemImpl();
      button.setLabelKey(buttonResetForm);
      button.setName(getName());
      button.setAction(ButtonItem.RESET_ACTION);
      button.setSave(false);
      vForm.addForm(button);

      button = new ButtonItemImpl();
      button.setLabelKey(buttonGoogleForm);
      button.setName(getName());
      button.setAction(ButtonItem.URL_ACTION);
      button.setSave(false);
      button.setUrl("http://www.google.fr/");
      vForm.addForm(button);

      /**
       * ************************************************Final
       * Panel*******************************************
       */

      // RichTextArea.
      final VerticalFormImpl vForm2_0 = new VerticalFormImpl();
      vForm2_0.setName("vForm2_0");
      final LabeledFormImpl secondForm = new LabeledFormImpl();
      secondForm.setName("secondForm");
      secondForm.setLabel(i18nMessageTab2);
      secondForm.setSubForm(vForm2_0);

      final RichTextAreaItemImpl richTextAreaTab3 = getRichTextArea();
      richTextAreaTab3.setValidator(new LongValidator());

      vForm2_0.addForm(richTextAreaTab3);

      TabFormImpl tabForm2 = new TabFormImpl();
      tabForm2.setName("tabForm2");
      for (int i = 0; i < 3; i++) {
        final LabeledFormImpl lForm = new LabeledFormImpl();
        lForm.setName("lForm" + i);
        lForm.setLabel(i18nMessageTab2);
        lForm.setSubForm(getRichTextArea());
        tabForm2.addForm(lForm);
      }
      vForm2_0.addForm(tabForm2);

      demo.addForm(secondForm);

      final LabeledFormImpl thirdForm = new LabeledFormImpl();
      thirdForm.setName("thirdForm");
      thirdForm.setLabel(i18nMessageTab3);
      final VerticalFormImpl vForm3 = new VerticalFormImpl();
      vForm3.setName("vForm3");
      thirdForm.setSubForm(vForm3);

      final ImageItemImpl myImageItem = new ImageItemImpl();
      myImageItem.setUrl("http://www.google.com/images/logo.gif");
      myImageItem.setName(getName());

      vForm3.addForm(myImageItem);

      final TextAreaItemImpl text = new TextAreaItemImpl();
      text.setLabelKey(i18nMessageTextArea);
      text.setValidator(new LongValidator());
      text.setName(getName());

      vForm3.addForm(text);

      demo.addForm(thirdForm);
    }

    return demo;

  }



  private static RichTextAreaItemImpl getRichTextArea()
  {
    final RichTextAreaItemImpl richTextAreaTab3 = new RichTextAreaItemImpl();
    richTextAreaTab3.setLabelKey(i18nMessageRichTextArea);
    richTextAreaTab3.setName(getName());
    return richTextAreaTab3;
  }



  public String getDisplayString(final String fieldName, final String value)
  {
    if (value == null) {
      return null;
    }
    return values[Integer.parseInt(value)];
  }



  public String getFormIdentifier()
  {
    return "demo";
  }



  /*
   * (non-Javadoc)
   * @see
   * com.genia.toolbox.web.gwt.form.server.provider.FormProvider#getSuggestions
   * (java.lang.String, java.lang.String, int)
   */
  public List<SimpleSuggestion> getSuggestions(DataIdentifier dataIdentifier, final String fieldName, final String query, final int limit)
  {
    final List<SimpleSuggestion> res = new ArrayList<SimpleSuggestion>();
    for (int i = 0; i < values.length; i++) {
      if (query != null && !values[i].toLowerCase().contains(query)) {
        continue;
      }
      final SimpleSuggestion suggestion = new SimpleSuggestion();
      suggestion.setDisplayString(values[i]);
      suggestion.setValue(String.valueOf(i));
      res.add(suggestion);
    }
    return res;
  }

}
